package com.jeesite.modules.aliyun.oss.service.impl;

import com.aliyun.oss.OSSClient;
import com.jeesite.common.io.FileUtils;
import com.jeesite.modules.aliyun.oss.bean.AliyunOSS;
import com.jeesite.modules.file.entity.FileEntity;
import com.jeesite.modules.file.entity.FileUpload;
import com.jeesite.modules.file.service.support.FileUploadServiceExtendSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * 文件上传阿里云 v4.1.7+
 * @author hzy
 * @version 2019年12月17日
 */
@Service
public class OssFileUploadServiceExtendImpl extends FileUploadServiceExtendSupport {

    @Autowired
    AliyunOSS aliyunOSS;
    @Value("${oss.bucketName}")
    String bucketName;
    @Value("${oss.endPoint}")
    String endPoint;
    @Value("${oss.downloadHost}")
    String downloadHost;

    @Value("${oss.endPoint}")
    private String endpoint;

    @Value("${oss.accessKeyId}")
    private String accessKeyId;

    @Value("${oss.accessKeySecret}")
    private String accessKeySecret;

    OSSClient ossClient;

    /**
     * 验证文件是否真实的存在
     * @param fileEntity 文件实体信息
     * @return 文件存在true，不存在false
     */
    @Override
    public boolean fileExists(FileEntity fileEntity){
        ossClient = aliyunOSS.ossClient();
        String path = removeFirstStr(fileEntity.getFileUrl());
        boolean found = fileExist(ossClient, path);
        return found;
    }

    /**
     * 上传文件，首次上传文件都调用（保存到文件实体表之前调用）
     * @param fileEntity 文件实体信息
     * @ fileEntity.getFileRealPath() 文件实际磁盘路径
     * @exception  throw ServiceException("文件不符合要求") v4.1.5
     */
    @Override
    public void uploadFile(FileEntity fileEntity){
        // 上传文件流。
        InputStream inputStream = null;
        ossClient = aliyunOSS.ossClient();
        try {
            inputStream = new FileInputStream(fileEntity.getFileRealPath());
            uploadFile(ossClient, inputStream, removeFirstStr(fileEntity.getFileUrl()));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 保存上传文件信息，每次上传都调用（保存文件和用户关系数据之前调用）
     * @param fileUpload 文件上传信息，包括文件实体
     * @exception  throw ServiceException("文件不符合要求") v4.1.5
     */
    @Override
    public void saveUploadFile(FileUpload fileUpload){

    }

    /**
     * 获取文件下载的URL地址
     * @param fileUpload 文件上传的信息，包括文件实体
     * @return 无文件下载地址，则返回null，方便后续处理
     */
    @Override
    public String getFileUrl(FileUpload fileUpload){
        return downloadHost + fileUpload.getFileEntity().getFileUrl();
    }

    /**
     * 下载文件到浏览器
     * @param fileUpload 文件上传的信息
     * @param request 请求对象，可能断点续传用
     * @param response 响应对象，输出文件流使用
     * @return 如果不是文件流数据，也可返回文件的URL地址进行跳转，如果文件不存在返回404字符串
     */
    @Override
    public String downFile(FileUpload fileUpload, HttpServletRequest request, HttpServletResponse response){
        FileEntity fileEntity = fileUpload.getFileEntity();
        File file = new File(fileEntity.getFileRealPath());
        if (file.exists()){
            FileUtils.downFile(file, request, response, fileUpload.getFileName());
            return null;
        }
        return "404";
    }

    /**
     * 上传本地文件
     * @param originFile 本地文件地址
     * @exception  throw ServiceException("文件不符合要求") v4.1.5
     */
    public void uploadFile(String originFile, String filePath){
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(originFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        uploadFile(ossClient, inputStream, filePath);
    }
    /**
     * 上传流文件
     * @param inputStream 流
     * @exception  throw ServiceException("文件不符合要求") v4.1.5
     */
    public void uploadFile(InputStream inputStream, String filePath){
        ossClient = aliyunOSS.getOssClient();
        uploadFile(ossClient, inputStream, filePath);
    }
    /**
     * 上传流文件
     * @param inputStream 流
     * @exception  throw ServiceException("文件不符合要求") v4.1.5
     */
    public void uploadFile(OSSClient ossClient, InputStream inputStream, String filePath){
        if(ossClient == null){
            ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        }
        if(filePath.startsWith("/")){
            filePath = removeFirstStr(filePath);
        }
        ossClient.putObject(bucketName, filePath, inputStream);
        logger.info("上传文件成功");
    }
    /**
     * 上传数组
     * @param data
     * @exception  throw ServiceException("文件不符合要求") v4.1.5
     */
    public void uploadFile(OSSClient ossClient, byte[] data, String filePath){
        if(ossClient == null){
            ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        }
        if(filePath.startsWith("/")){
            filePath = removeFirstStr(filePath);
        }
        ossClient.putObject(bucketName, filePath, new ByteArrayInputStream(data));
        logger.info("上传文件成功");
    }

    /**
     * 文件是否存在
     * @param ossClient
     * @param filePath
     */
    public boolean fileExist(OSSClient ossClient, String filePath){
        if(ossClient == null){
            ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        }
        if(filePath.startsWith("/")){
            filePath = removeFirstStr(filePath);
        }
        boolean found = ossClient.doesObjectExist(bucketName, filePath);
        return found;
    }

    private String removeFirstStr(String url){
        return url.substring(1);
    }
}
